﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace Nollie.Utilities
{
	public class KeyIndexCollection : IEnumerable
	{
		private Dictionary<string, Entry> _dictionary;
		private List<Entry> _list;

		public int Count
		{
			get
			{
				return _list.Count;
			}
		}

		public KeyIndexCollection(int capacity)
		{
			_dictionary = new Dictionary<string, Entry>(capacity);
			_list = new List<Entry>(capacity);
		}

		public virtual void BaseAdd(string key, object value)
		{
			var entry = new Entry(key, value);

			_dictionary.Add(key, entry);
			_list.Add(entry);
		}
		public virtual object BaseGet(int index)
		{
			var entry = _list[index];

			if (entry == null)
				return null;

			return entry.Value;
		}
		public virtual object BaseGet(string key)
		{
			if (_dictionary.ContainsKey(key))
			{
				var entry = _dictionary[key];

				if (entry != null)
					return entry.Value;
			}

			return null;
		}
		public virtual void BaseRemove(string key)
		{
			if (!_dictionary.ContainsKey(key))
				return;

			var item = _dictionary[key];

			_dictionary.Remove(key);
			_list.Remove(item);
		}
		public virtual void BaseRemoveAt(int index)
		{
			var entry = _list[index];

			if (entry == null)
				throw new Exception("Entry not found.");

			_list.RemoveAt(index);
			_dictionary.Remove(entry.Key);
		}
		public virtual void BaseClear()
		{
			_dictionary.Clear();
			_list.Clear();
		}

		public KeyIndexEnumerator GetEnumerator()
		{
			return new KeyIndexEnumerator(_list);
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return (IEnumerator) GetEnumerator();
		}
	}

	public class KeyIndexEnumerator : IEnumerator
	{
		private List<Entry> _list;

		int position = -1;

		public KeyIndexEnumerator(List<Entry> list)
		{
			_list = list;
		}

		public bool MoveNext()
		{
			position++;
			return (position < _list.Count);
		}

		public void Reset()
		{
			position = -1;
		}

		object IEnumerator.Current
		{
			get
			{
				return Current;
			}
		}

		public object Current
		{
			get
			{
				try
				{
					return _list[position].Value;
				}
				catch (IndexOutOfRangeException)
				{
					throw new InvalidOperationException();
				}
			}
		}
	}

	public class Entry
	{
		public string Key
		{
			get;
			set;
		}
		public object Value
		{
			get;
			set;
		}

		public Entry(string key, object value)
		{
			this.Key = key;
			this.Value = value;
		}
	}
}
